package com.cmc.cloud.cmclink.doc.service.impl.si;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cmc.cloud.cmclink.doc.api.document.emums.SiValidEnum;
import com.cmc.cloud.cmclink.doc.constants.DateFormatterConstants;
import com.cmc.cloud.cmclink.doc.constants.errorconstant.BlnoCntrRecordationErrorCodeConstants;
import com.cmc.cloud.cmclink.doc.constants.errorconstant.BlnoErrorCodeConstants;
import com.cmc.cloud.cmclink.doc.convert.BlnoCntrRecordationConvert;
import com.cmc.cloud.cmclink.doc.entity.BlnoCntrRecordationDO;
import com.cmc.cloud.cmclink.doc.entity.BlnoDO;
import com.cmc.cloud.cmclink.doc.entity.SoDO;
import com.cmc.cloud.cmclink.doc.mapper.BlnoCntrMapper;
import com.cmc.cloud.cmclink.doc.mapper.BlnoCntrRecordationMapper;
import com.cmc.cloud.cmclink.doc.mapper.BlnoMapper;
import com.cmc.cloud.cmclink.doc.mapper.SoMapper;
import com.cmc.cloud.cmclink.doc.service.si.BlnoCntrRecordationService;
import com.cmc.cloud.cmclink.doc.util.EmailUtil;
import com.cmc.cloud.cmclink.doc.vo.blnocntrrecordationvo.BlnoCntrRecordationCreateReqVO;
import com.cmc.cloud.cmclink.doc.vo.blnocntrrecordationvo.BlnoCntrRecordationOperationVO;
import com.cmc.cloud.cmclink.doc.vo.blnocntrrecordationvo.BlnoCntrRecordationPageReqVO;
import com.cmc.cloud.cmclink.doc.vo.blnocntrrecordationvo.BlnoCntrRecordationQuery;
import com.cmc.cloud.cmclink.doc.vo.blnocntrrecordationvo.BlnoCntrRecordationUpdateReqVO;
import com.cmc.cloud.cmclink.eqm.api.model.request.OrderContactFormQueryParam;
import com.cmc.cloud.cmclink.eqm.api.model.response.OrderContactFormDTO;
import com.cmc.cloud.cmclink.eqm.api.resource.OrderContactFormApi;
import com.cmes.framework.common.exception.util.ServiceExceptionUtil;
import com.cmes.framework.common.pojo.CommonResult;
import com.cmes.framework.common.pojo.PageResult;
import com.cmes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cmes.platform.system.nuc.NucApi;
import com.cmes.platform.system.nuc.dto.UserProfileDTO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.cmc.cloud.cmclink.doc.api.document.emums.SiEmailDataSoureceEnum.CMCLINK;
import static com.cmc.cloud.cmclink.doc.api.document.emums.SiEmailDataSoureceEnum.WEB_BUSINESS;

/**
 * 提单箱况备案 Service 实现类
 *
 * @author 集运管理员
 */
@Service
@Validated
public class BlnoCntrRecordationServiceImpl implements BlnoCntrRecordationService {

    @Resource
    private BlnoCntrRecordationMapper blnoCntrRecordationMapper;

    @Resource
    private BlnoCntrMapper blnoCntrMapper;

    @Resource
    private BlnoMapper blnoMapper;

    @Resource
    private EmailUtil emailUtil;

    @Resource
    private NucApi nucApi;

    @Resource
    private OrderContactFormApi orderContactFormApi;

    @Resource
    private SoMapper soMapper;

//    private static final String ADMIN_DEFAULT_EMAIL = "linzj@deepinsights.com.cn";

    private static final String ADMIN_DEFAULT_EMAIL = "1033370309@qq.com";

    private static final String PROMPT = "【Missing POL EMAIL】";

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createBlnoCntrRecordation(BlnoCntrRecordationOperationVO blnoCntrRecordationOperationVO) {
        List<BlnoCntrRecordationCreateReqVO> createReqVO = blnoCntrRecordationOperationVO.getCreateReqVO();
        BlnoCntrRecordationCreateReqVO recordationCreateReqVO = createReqVO.get(0);
        List<BlnoCntrRecordationDO> blnoCntrRecordationDos =
                BeanUtil.copyToList(createReqVO, BlnoCntrRecordationDO.class);
        if (CollectionUtil.isEmpty(createReqVO)) {
            return;
        }
        boolean flag = WEB_BUSINESS.getValue().equals(blnoCntrRecordationOperationVO.getDataSource());
        BlnoDO blnoDO;
        if (flag) {
            if (StringUtils.isEmpty(blnoCntrRecordationOperationVO.getUserId()) || StringUtils.isEmpty(blnoCntrRecordationOperationVO.getNickName())) {
                throw ServiceExceptionUtil
                        .exception(BlnoCntrRecordationErrorCodeConstants.BLNO_CNTR_PARAM_LACK);
            }
            SoDO soDo = soMapper.selectOne(new LambdaQueryWrapper<SoDO>()
                            .eq(SoDO::getBookingNo, recordationCreateReqVO.getBookingNo()).eq(SoDO::getValidStatus, SiValidEnum.VALID.getValue())
                            .last("limit 1"));
            blnoCntrRecordationDos.forEach(n -> n.setBlno(soDo.getBlNo()));
            blnoDO = BeanUtil.copyProperties(soDo, BlnoDO.class);
            blnoDO.setBkgVesselCode(soDo.getBookingVessel());
            blnoDO.setBkgVoyage(soDo.getBookingVoyage());
        } else {
            //网厅-so的时候创建箱况备案,故此修改
            List<BlnoDO> blnoDos = blnoMapper
                    .selectList(new LambdaQueryWrapper<BlnoDO>()
                            .eq(BlnoDO::getBookingNo, recordationCreateReqVO.getBookingNo()).eq(BlnoDO::getValid, SiValidEnum.VALID.getValue())
                            .last("limit 1"));
            if (CollectionUtil.isEmpty(blnoDos)) {
                throw ServiceExceptionUtil.exception(BlnoErrorCodeConstants.BLNO_NOT_EXISTS);
            }
            blnoDO = blnoDos.get(0);
            blnoCntrRecordationDos.forEach(n ->{
                n.setBlno(blnoDO.getBlNo());
                if (n.getId() == null) {
                    n.setCreator(blnoCntrRecordationOperationVO.getUserId());
                }
                n.setUpdater(blnoCntrRecordationOperationVO.getUserId());
            });
        }
        createOrUpdateOrDelete(blnoCntrRecordationDos, recordationCreateReqVO.getBookingNo());
        // 发送邮件,设置模版内参数
        List<OrderContactFormDTO> checkedData = null;
        try {
            OrderContactFormQueryParam orderContactFormQueryParam = new OrderContactFormQueryParam();
            orderContactFormQueryParam.setOrderType("箱况备案");
            orderContactFormQueryParam.setPortCodeList(Arrays.asList(blnoDO.getPorCode(), blnoDO.getDelCode()));
            CommonResult<List<OrderContactFormDTO>> query = orderContactFormApi.query(orderContactFormQueryParam);
            if (query != null) {
                checkedData = query.getCheckedData();
            }
        } catch (Exception e) {
            throw ServiceExceptionUtil
                    .exception(BlnoCntrRecordationErrorCodeConstants.BLNO_EQU_FAILURE);
        }
        List<String> notifyEmails = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(checkedData)) {
            notifyEmails = checkedData.stream().map(OrderContactFormDTO::getContact).distinct().collect(Collectors.toList());
        }
        String nickname = "";
        if (!flag) {
            CommonResult<UserProfileDTO> userProfile = nucApi.getUserProfile();
            nickname = userProfile.getCheckedData().getNickname();
        }
        Map<String, Object> model = new HashMap<>(8);
        model.put("bookingNo", blnoDO.getBookingNo());
        model.put("containerNos", createReqVO.stream().map(BlnoCntrRecordationCreateReqVO::getCntrNo).collect(Collectors.joining(", ")));
        model.put("polCode", blnoDO.getPolCode());
        model.put("podCode", blnoDO.getPodCode());
        model.put("delCode", blnoDO.getDelCode());
        model.put("vesselVoyage", blnoDO.getBkgVesselCode() + "/" + blnoDO.getBkgVoyage());
        model.put("operator", flag ? blnoCntrRecordationOperationVO.getNickName() : nickname);
        model.put("operateTime", LocalDateTime.now().format(DateFormatterConstants.FORMATTER_AMEND3));
        model.put("datasource", flag ? blnoCntrRecordationOperationVO.getDataSource() : CMCLINK.getValue());
        model.put("prompt", "");
        if (CollectionUtil.isNotEmpty(notifyEmails)) {
            notifyEmails.forEach(eamil -> {
                emailUtil.sendMail(eamil, "cntrRecordation", model);
            });
        } else {
            model.put("prompt", PROMPT);
            emailUtil.sendMail(ADMIN_DEFAULT_EMAIL, "cntrRecordation", model);
        }
    }

    private void createOrUpdateOrDelete(List<BlnoCntrRecordationDO> blnoCntrRecordationDos, String bookingNo) {
        // 删除 原数据
        blnoCntrRecordationMapper.deleteByBlno(bookingNo);
        // 重新绑定
        blnoCntrRecordationMapper.insertBatch(blnoCntrRecordationDos);
    }

    @Override
    public void updateBlnoCntrRecordation(BlnoCntrRecordationUpdateReqVO updateReqVO) {
        // 校验存在
        validateBlnoCntrRecordationExists(updateReqVO.getId());
        // 更新
        BlnoCntrRecordationDO updateObj = BlnoCntrRecordationConvert.INSTANCE.convert(updateReqVO);
        blnoCntrRecordationMapper.updateById(updateObj);
    }

    @Override
    public void deleteBlnoCntrRecordation(Long id) {
        // 校验存在
        validateBlnoCntrRecordationExists(id);
        // 删除
        blnoCntrRecordationMapper.deleteById(id);
    }

    private void validateBlnoCntrRecordationExists(Long id) {
        if (blnoCntrRecordationMapper.selectById(id) == null) {
            throw ServiceExceptionUtil
                    .exception(BlnoCntrRecordationErrorCodeConstants.BLNO_CNTR_RECORDATION_NOT_EXISTS);
        }
    }

    @Override
    public BlnoCntrRecordationDO getBlnoCntrRecordation(Long id) {
        return blnoCntrRecordationMapper.selectById(id);
    }

    @Override
    public List<BlnoCntrRecordationDO> getCntrRecordationList(BlnoCntrRecordationQuery queryCntrRecord) {
        LambdaQueryWrapperX<BlnoCntrRecordationDO> queryWrapperX = new LambdaQueryWrapperX<BlnoCntrRecordationDO>()
                .likeIfPresent(BlnoCntrRecordationDO::getBlno, queryCntrRecord.getBlno())
                .likeIfPresent(BlnoCntrRecordationDO::getCntrNo, queryCntrRecord.getCntrNo())
                .likeIfPresent(BlnoCntrRecordationDO::getBookingNo, queryCntrRecord.getBookingNo());
        return blnoCntrRecordationMapper.selectList(queryWrapperX);
    }

    @Override
    public List<BlnoCntrRecordationDO> getBlnoCntrRecordationList(Collection<Long> ids) {
        return blnoCntrRecordationMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<BlnoCntrRecordationDO> getBlnoCntrRecordationPage(BlnoCntrRecordationPageReqVO reqVO) {
        IPage<BlnoCntrRecordationDO> page = Page.of(reqVO.getPageNo(), reqVO.getPageSize());

        IPage<BlnoCntrRecordationDO> result = blnoCntrRecordationMapper.selectPageList(page, reqVO);
        return new PageResult<BlnoCntrRecordationDO>(result.getRecords(), result.getTotal());
    }
}
